package com.mango.acat.core.server.netty;

import java.io.IOException;
import java.security.cert.CertificateException;

import javax.net.ssl.SSLException;

import org.apache.log4j.Logger;

import com.mango.acat.core.server.AcatHttpServerInitializer;
import com.mango.acat.core.server.IServer;
import com.mango.acat.core.setting.AppSetting;
import com.mango.acat.core.util.InitKit;
import com.mango.acat.core.util.thread.PriorityThreadFactory;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.Channel;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.ssl.SslContext;
import io.netty.handler.ssl.util.SelfSignedCertificate;

public class NettyServer implements IServer {
	private static Logger _log = Logger.getLogger(NettyServer.class);
	private int subThreadNum = 0;
	private Channel ch = null;
	private int port;

	public NettyServer(int subThreadNum) {
		this.subThreadNum = subThreadNum;
	}

	public NettyServer() {
		
	}

	@SuppressWarnings("deprecation")
	public void start(int port) {
		this.port = port;
		EventLoopGroup bossGroup = new NioEventLoopGroup(Runtime.getRuntime().availableProcessors(),
				new PriorityThreadFactory("Netty(" + port + ")主线程池", 5));
		EventLoopGroup workerGroup = new NioEventLoopGroup(
				this.subThreadNum == 0 ? Runtime.getRuntime().availableProcessors() * 2 : this.subThreadNum,
				new PriorityThreadFactory("Netty(" + port + ")子线程", 5));
		try {
			Boolean webSSLFlag = Boolean.valueOf(false);
			SslContext sslCtx;
			if (webSSLFlag.booleanValue()) {
				SelfSignedCertificate ssc = new SelfSignedCertificate();
				sslCtx = SslContext.newServerContext(ssc.certificate(), ssc.privateKey());
			} else {
				sslCtx = null;
			}
			ServerBootstrap b = new ServerBootstrap();
			b.group(bossGroup, workerGroup).channel(NioServerSocketChannel.class);
			b.childHandler(new AcatHttpServerInitializer(sslCtx));
			b.option(ChannelOption.SO_BACKLOG, 128);
            b.childOption(ChannelOption.SO_KEEPALIVE, true);
            //acat启动日志
            System.out.println();
            System.out.println("	     ##         ########        ##         #############");
            System.out.println("	    ####       ####            ####             ##");
            System.out.println("	   #    #     ####            #    #            ##");
            System.out.println("	  ########   ####            ########           ##");
            System.out.println("	##        ##  ####          ##      ##          ##");  
            System.out.println("   ##          ##  ####        ##        ##         ##");
           	System.out.println("  ##            ##  ########  ##          ##        ##");
			 //加载注解，组装请求类容器
	        InitKit.initReqKey();
	        //加载通用的freemarker模板
	        InitKit.initCommonFreemarker();
			this.ch = b.bind(port).sync().channel();
			if (_log.isInfoEnabled()) {
				_log.info((webSSLFlag.booleanValue() ? "Https" : "Http") + "服务器启动成功，端口为：" + port + ",版本号为:"
						+ AppSetting.app.getStr("app.version"));
			}
			this.ch.closeFuture().sync();
		} catch (InterruptedException e) {
			_log.error(e.getMessage(), e);
		} catch (CertificateException e) {
			_log.error(e.getMessage(), e);
		} catch (SSLException e) {
			_log.error(e.getMessage(), e);
		} catch (IOException e) {
			_log.error(e.getMessage(), e);
		} finally {
			bossGroup.shutdownGracefully();
			workerGroup.shutdownGracefully();
		}
	}

	public void stop() {
		if (this.ch != null) {
			this.ch.close();
		}
	}

	public void restart() {
		stop();
		start(this.port);
	}
}
